/**
 * 表格 (数据类)
 */
function sTable(target) {
    if(this.initialize) return;
    
    var thiz = target ? target : this;

    sElement.call(this, "sTable");

    this.style = thiz.style ? thiz.style : {};
    
    var display = "block";

    /**
     * 定义样式的display
     */
    Object.defineProperty(this.style, "display", {
        get: ()=>{
            return display;
        },
        set: (value)=>{
            display = value == "none" ? "none" : "block";
        }
    });

    var columns = [];
    var rows = [];

    if(thiz.columns){
        columns = thiz.columns;
    }

    if(thiz.rows){
        rows = thiz.rows;
    }

    /**
     * 获取列集合
     * @returns 
     */
    this.getColumns = function(index){
        if(index != null){
            return columns[index];
        }
        return columns;
    }

    /**
     * 获取列的总宽度
     */
    this.getColsWidth = function(range){
        var width = 0;
        for(var i = 0; i < columns.length; i++){
            if(range && (i < range[0] || i > range[1])) continue;
            width += columns[i].style.width;
        }
        return width;
    }

    /**
     * 获取行集合
     * @param {*} index 行序号，可选
     * @returns 
     */
    this.getRows = function(index){
        if(index != null){
            return rows[index];
        }
        return rows;
    }

    /**
     * 获取总行数
     * @returns 
     */
    this.getRowCount = function(){
        return rows.length;
    }

    /**
     * 获取总列数
     * @returns 
     */
    this.getColCount = function(){
        return columns.length;
    }

    /**
     * 获取合并单元格
     * @param {*} rowIndex 
     * @param {*} colIndex 
     * @param {*} outParam
     */
    this.getSpanCell = function(rowIndex, colIndex, outParam){
        let row = null;
        let cell = null;

        for(let i = rowIndex; i >= 0; i--){
            row = rows[i];

            for(let j = colIndex; j >= 0; j--){
                cell = row.getCells(j);

                if(cell.style.display != "none"){
                    if(cell.colspan + j - 1 >= colIndex && 
                        cell.rowspan + i - 1 >= rowIndex){
                        
                        if(outParam){
                            outParam.rowIndex = i;
                            outParam.columnIndex = j;
                        }

                        return cell;
                    }
                }
            }
        }
        
        return null;
    }

    /**
     * 实例化表格列
     * @returns 
     */
    this.instanceColumn = function(target){
        return new sTableColumn(target);
    }

    /**
     * 创建表格行元素
     * @returns 
     */
    this.instanceRow = function(target){
        return new sTableRow(target);
    }

    /**
     * 创建合并单元格代理对象
     * @param {*} cell 单元格
     * @param {*} rowIndex 行序号
     * @param {*} colIndex 列序号
     */
    this.createSpanCellProxy = function(cell, rowIndex, colIndex){
        return new spanCellProxy(cell, rowIndex, colIndex);
    }

    /**
     * 将表格元素转成字符串
     */
    this.toString = function(){
        var obj = {
            columns: columns,
            rows: []
        };

        for(var i = 0; i < rows.length; i++){
            obj.rows.push(rows[i].getCells())
        }

        return JSON.stringify(obj, (key, value) => {
            if(value === null || value === undefined || key.indexOf("__") > -1){
                return undefined;
            }
            return value;
        });
    }

    /**
     * 列
     */
    function sTableColumn(target){
        this._sType = "sTableColumn";
        
        var thiz = target ? target : this;

        this.style = thiz.style ? thiz.style : {};
        this.attributes = thiz.attributes ? thiz.attributes : null;
    }

    //定义列的最小宽度
    Object.defineProperty(sTableColumn.prototype, "MIN_WIDTH", {
        get: function(){
            return 10;
        },
        enumerable: false
    });

    /**
     * 行
     */
    function sTableRow(target){
        this._sType = "sTableRow";

        var thiz = target ? target : this;
        var cells = [];

        this.style = {
            ...thiz.style
        };

        if(thiz.cells){
            cells = thiz.cells;
        }

        if(thiz.head){
            this.head = thiz.head;
        }

        /**
         * 获取单元格元素集合
         * @param {*} index 单元格序号，可选
         * @returns 
         */
        this.getCells = function(index){
            if(index != null){
                return cells[index];
            }
            return cells;
        }

        /**
         * 创建表格单元格元素
         * @returns 
         */
        this.instanceCell = function(target){
            return new sTableCell(target);
        }

        /**
         * 插入单元格
         * @param {*} index
         * @param {*} option
         * @returns 
         */
        this.insertCell = function(index, option){
            var cell = new sTableCell();
            return this.insertCellObj(index, cell, option);
        }

        /**
         * 插入单元格
         * @param {*} index
         * @param {*} cell
         * @param {*} option
         * @returns 
         */
        this.insertCellObj = function(index, cell, option){
            if(index != null){
                cells.splice(index, 0, cell);
            }else{
                cells.push(cell);
            }

            cell.parent = this;
            Object.defineProperty(cell, "parent", {enumerable: false});

            return cell;
        }

        /**
         * 清除内部单元格
         */
        this.clear = function(){
            cells = [];
            return this;
        }
    }

    /**
     * 克隆行
     * @param {*} deep 深度克隆
     */
    var cloneRow = function(deep){
        let tableRow = new sTableRow(this);

        if(deep){
            let tableCells = tableRow.getCells();
            let cells = this.getCells();
            
            for(let i in cells){
                tableCells.push(cells[i].clone(deep));
            }
        }

        return tableRow;
    };

    /**
     * 克隆方法
     */
    sTableRow.prototype.clone = cloneRow;

    /**
     * 单元格
     */
    function sTableCell(target){
        this._sType = "sTableCell";

        var thiz = target ? target : this;

        this.rowspan = 1;
        this.colspan = 1;

        if(thiz.rowspan){
            this.rowspan = parseInt(thiz.rowspan);
        }

        if(thiz.colspan){
            this.colspan = parseInt(thiz.colspan);
        }

        if(thiz.gridLines){
            this.gridLines = thiz.gridLines;
        }

        if(!thiz.children){
            this.children = [];
        }

        this.style = {
            padding: "4,14,4,8",
            minHeight: 32,
            align: "middleLeft",
            ...thiz.style
        };

        if(!this.style.borderTop && 
           !this.style.borderBottom && 
           !this.style.borderLeft && 
           !this.style.borderRight &&
           !this.style.border){
            this.style.border = {
                width: 1,
                color: "#606266"
            };
        }

        this.children = thiz.children ? thiz.children : [];

        sElement.call(this);

        /**
         * 清除内部子元素
         */
        this.clear = function(){
            this.children = [];
            return this;
        }
    }

    /**
     * 克隆单元格
     */
    var cloneCell = function(deep){
        let cell = new sTableCell(this);
        
        if(deep){
            let children = cell.children;
            cell.children = [];

            for(let i in children){
                if(!children[i].clone) continue;
                cell.children.push(children[i].clone());
            }
        }

        return cell;
    }

    sTableCell.prototype.clone = cloneCell;

    /**
     * 代理合并单元格
     * @param {*} cell 合并单元格
     * @param {*} rowIndex 单元格所在行
     * @param {*} colIndex 单元格所在列
     */
    function spanCellProxy(cell, rowIndex, colIndex){
        var range = {
            top: rowIndex,
            left: colIndex,
            bottom: rowIndex + cell.rowspan,
            right: colIndex + cell.colspan
        }

        var refCell = cell;

        var props = {};
        
        /**
         * 获取行序号
         */
        this.getRowIndex = function(){
            return rowIndex;
        }

        /**
         * 获取列序号
         */
        this.getColIndex = function(){
            return colIndex;
        }

        /**
         * 获取跨行数
         * @returns 
         */
        this.getRowspan = function(){
            return parseInt(cell.rowspan);
        }

        /**
         * 获取跨列数
         * @returns 
         */
        this.getColspan = function(){
            return parseInt(cell.colspan);
        }

        /**
         * 判断当前的所在行列的单元格是否被包含在合并单元格内
         * @param {*} rowIndex 行序号
         * @param {*} colIndex 列序号
         */
        this.include = function(rowIndex, colIndex){
            if(rowIndex != null && colIndex != null){
                return rowIndex >= range.top && 
                    rowIndex < range.bottom &&
                    colIndex >= range.left && 
                    colIndex < range.right;
            }else if(rowIndex != null && colIndex == null){
                return rowIndex >= range.top && 
                    rowIndex < range.bottom;
            }else if(rowIndex == null && colIndex != null){
                return colIndex >= range.left && 
                    colIndex < range.right;
            }
            return false;
        }

        /**
         * 获取原始合并单元格
         * @returns 
         */
        this.getRef = function(){
            return refCell;
        }

        /**
         * 设置属性
         * @param {*} name 
         * @param {*} value 
         */
        this.setProp = function(name, value){
            props[name] = value;
        }

        /**
         * 获取属性
         * @param {*} name 
         * @returns 
         */
        this.getProp = function(name){
            return props[name];
        }
    }

    /**
     * 插入新行
     * @param {*} index 插入的位置
     * @param {*} option 可选项
     */
    this.insertRow = function(index, option){
        var row = new sTableRow();
        return this.insertRowObj(index, row, option);
    }

    /**
     * 插入行对象
     * @param {*} index 插入的位置
     * @param {*} row 行对象
     * @param {*} option 可选项
     * @returns 
     */
    this.insertRowObj = function(index, row, option){
        if(index != null){
            rows.splice(index, 0, row);
        }else{
            rows.push(row);
        }

        row.parent = this;
        Object.defineProperty(row, "parent", {enumerable: false});

        return row;
    }

    /**
     * 插入新列
     * @param {*} index 插入的位置
     * @param {*} option 可选项
     * @returns 
     */
    this.insertColumn = function(index, option){
        var column = new sTableColumn();
        return this.insertColumnObj(index, column, option);
    }

    /**
     * 插入column对象
     * @param {*} index 插入的位置
     * @param {*} column column对象
     * @param {*} option 可选项
     */
    this.insertColumnObj = function(index, column, option){
        if(option){
            if(option.style){
                column.style = {...column.style, ...option.style};
            }
        }

        if(!column.style){
            column.style = {};
        }

        //计算列宽
        if(!column.style.width){
            let width = 0;
            for(let i in columns){
                width += columns[i].style.width;
            }

            let avgWidth = width / columns.length;
            column.style.width = avgWidth;

            avgWidth = avgWidth / columns.length;
            for(let i in columns){
                columns[i].style.width -= avgWidth;
            }
        }

        if(index != null){
            columns.splice(index, 0, column);
        }else{
            columns.push(column);
        }

        return column;
    }

    /**
     * 创建一个单元格对象
     * @returns 
     */
    this.createTableCell = function(){
        return new sTableCell();
    }
    
    /**
     * 创建一个表格列
     * @returns 
     */
    this.createTableColumn = function(){
        return new sTableColumn();
    }

    /**
     * 创建一个表格行
     * @returns 
     */
    this.createTableRow = function(){
        return new sTableRow();
    }
}

/**
 * 将sElement原型上的方法和属性赋值给sTable原型
 */
for(let i in sElement.prototype){
    sTable.prototype[i] = sElement.prototype[i];
}